# 聚合上提张力计算
import math
from typing import List

from common.params import SoftParams
from model.soft.soft_common import AxialForceResult, data_init, UniForceResult
from model.soft.fluid_resistance import tool_pull_fluid, tool_push_fluid
from model.soft.tool_fluid import get_tool_total_force

# 缆头张力只和仪器的液体阻力有关，只在最终结果上加或者减去带有速度的仪器液体阻力，同时减去其他的仪器液体阻力

# 计算 f 最新方法
def calc_f_push(D: float, params:  SoftParams, cur: AxialForceResult, pre: AxialForceResult, preN: float,
              preF: float) -> float:
    factor_b: float = math.cos(math.radians(pre.inclination))
    params.L1 = round(params.L1)
    # 测井仪器的单位浮重
    w1: float = params.w1
    # if (cur.depth >= D - params.L1) and cur.depth < D:
    if (cur.depth >= D - params.L1) and cur.depth < D:

        f: float = w1 * factor_b - params.get_mu_push(cur.depth) * preN + preF
        # if f == 0.0 or f is None:
        #     print("深度{}计算f为0".format(D))
        return f


# 计算 N 最新计算方法
def calc_n_push(D: float, params: SoftParams, cur: AxialForceResult, F: float) -> float:
    # 测井仪器的单位浮重
    w1: float = params.w1
    factor_a: float = cur.azimuth_rate
    factor_b: float = math.sin(math.radians(cur.inclination))
    factor_c: float = cur.inclination_rate
    # 范围修改
    # if (cur.depth >= 0) and (cur.depth <= D):
    if cur.depth == 0:
        n = 0.0
        return n
    if (cur.depth > 0) and (cur.depth <= D):
        factor_d: float = F * factor_a * factor_b
        factor_e: float = F * factor_c
        n: float = math.sqrt(math.pow(factor_d, 2) + math.pow(factor_e + w1 * factor_b, 2))
        # print("{} 深度 N 计算结果为:{}".format(D,n))
        return n


def calc_f_pull(D: float, params:  SoftParams, cur: AxialForceResult, pre: AxialForceResult, preN: float,
              preF: float) -> float:
    factor_b: float = math.cos(math.radians(pre.inclination))
    params.L1 = round(params.L1)
    # 测井仪器的单位浮重
    w1: float = params.w1
    # 电缆的单位浮重
    w2: float = params.w2
    # if (cur.depth >= D - params.L1) and (cur.depth < D):
    if (cur.depth >= D - params.L1) and (cur.depth < D):
        f: float = w1 * factor_b + params.get_mu_pull(cur.depth) * preN + preF
        # print("当前深度：{}，当前的上提F:{}".format(cur.depth,f))
        return f



# 计算 N 最新计算方法
def calc_n_pull(D: float, params: SoftParams, cur: AxialForceResult, F: float) -> float:
    # 测井仪器的单位浮重
    w1: float = params.w1
    factor_a: float = cur.azimuth_rate
    factor_b: float = math.sin(math.radians(cur.inclination))
    factor_c: float = cur.inclination_rate
    # 范围修改
    # if (cur.depth >= 0) and (cur.depth <= D):
    if cur.depth == 0:
        n = 0.0
        return n

    if (cur.depth > 0) and (cur.depth <= D):

        factor_d: float = F * factor_a * factor_b
        factor_e: float = F * factor_c
        n: float = math.sqrt(math.pow(factor_d, 2) + math.pow(factor_e + w1 * factor_b, 2))
        # print("{} 深度 N 计算结果为:{}".format(D,n))
        return n


# 计算正常下放的张力
# D 全井深
def calc_uni(D: float, params: SoftParams, cur: AxialForceResult, pre: AxialForceResult,
             _list_: List[AxialForceResult]) -> AxialForceResult:

    # 几种类型的点
    cur.F_push = calc_f_push(D, params, cur, pre, pre.N_push, pre.F_push)
    cur.N_push = calc_n_push(D, params, cur, cur.F_push)

    cur.F_pull = calc_f_pull(D, params, cur, pre, pre.N_pull, pre.F_pull)
    cur.N_pull = calc_n_pull(D, params, cur, cur.F_pull)


    return cur


# 迭代函数
def deep_func(idx: int, params: SoftParams, _list_: List[AxialForceResult], fluid_resistances_pull: dict, fluid_resistances_push: dict, is_Not_add_resistance: bool) -> UniForceResult:
    # 本次迭代深度 从 D 迭代到 D - L1
    D: float = _list_[idx].depth
    params.L1 = round(params.L1)
    # 四种类型的点
    _list_[idx].F_push = 0.0
    _list_[idx].N_push = calc_n_push(D, params, _list_[idx], _list_[idx].F_push)

    _list_[idx].F_pull = 0.0
    _list_[idx].N_pull = calc_n_pull(D, params, _list_[idx], _list_[idx].F_pull)

    # 求和次数
    count: int = round(params.L1) - 1
    # 求和值w
    sum_val: float = _list_[idx].N_push
    # sum_val: float = 0.0
    # print("sum_val为{}，当前深度为{}".format(sum_val,_list_[idx].depth))
    # 定义导出列表
    result: UniForceResult = UniForceResult()
    # -1 到达不了
    for i in range(idx - 1, -1, -1):
        _list_[i] = calc_uni(_list_[idx].depth, params, _list_[i], _list_[i + 1], _list_)
        # 移除 count = 0 条件也可
        # if count >= 0:
        #     # print("sumval新增了:{}".format(_list_[i].N_push))
        #     sum_val = sum_val + _list_[i].N_push
        #     count = count - 1

        sum_val = sum_val + _list_[i].N_push
        # 赋值操作
        result.depth = D
        if is_Not_add_resistance ==True:
            result.F_pull = _list_[i].F_pull + fluid_resistances_pull[D]
            # print("当前深度为{}，当前的上提F为{}，上提液体阻力为{}".format(D, _list_[i].F_pull, fluid_resistances_pull[D]))
            result.F_push = _list_[i].F_push - fluid_resistances_push[D]
            # print("当前深度为{}，当前的下放F为{}，下放液体阻力为{}".format(D, _list_[i].F_push, fluid_resistances_push[D]))
        else:
            result.F_pull = _list_[i].F_pull
            result.F_push = _list_[i].F_push
        result.N_pull = _list_[i].N_pull
        result.N_push = _list_[i].N_push
        result.N_sum = sum_val

        if _list_[i].depth <= D - params.L1:
            # print(JsonUtil.obj2str(result))
            return result


# 聚合构建 返回计算结果
def uni_build(params: SoftParams, _list_: List[AxialForceResult], is_Not_add_resistance: bool, desired_depths: List[float]) -> List[UniForceResult]:
    # T 为张力
    t: List[UniForceResult] = []
    params.L1 = round(params.L1)
    data_len = len(_list_)
    # 计算所有深度点的液体阻力
    fluid_resistances_pull = {}
    fluid_resistances_push = {}

    for idx in range(data_len):
        fluid_resistances_pull[_list_[idx].depth] = tool_pull_fluid(params, _list_[idx]) - get_tool_total_force(params)
        fluid_resistances_push[_list_[idx].depth] = tool_push_fluid(params, _list_[idx]) + get_tool_total_force(params)
        # fluid_resistances_pull[_list_[idx].depth] = tool_pull_fluid(params, _list_[idx])
        # fluid_resistances_push[_list_[idx].depth] = tool_push_fluid(params, _list_[idx])

    # 设置迭代次数 判断当前深度是不是在间隔的列表里 如果在间隔列表里才进行迭代计算 否则不计算
    for depth in desired_depths:
        # 找到对应深度在 _list_ 中的索引
        idx = next((i for i, item in enumerate(_list_) if item.depth >= depth), None)
        if idx is not None and idx >= params.L1:
            # print("==========={}==============".format(idx))
            t_item: UniForceResult = deep_func(idx, params, _list_, fluid_resistances_pull, fluid_resistances_push,is_Not_add_resistance)
            # print("==========={}==============".format(idx))
            # print(JsonUtil.obj2str(t_item))
            t.append(t_item)
    return t


def run(params: SoftParams, _list_, is_Not_add_resistance: bool, desired_depths: List[float]) -> List[UniForceResult]:
    # 数据预处理
    result_arr: List[AxialForceResult] = data_init(_list_)
    # for item in result_arr:
    #     print(JsonUtil.obj2str(item))
    # 计算结果
    result: List[UniForceResult] = uni_build(params, result_arr,is_Not_add_resistance, desired_depths)
    # 此处数据不处理
    return result


